#!/usr/bin/env python3
# -*- coding: utf-8 -*-

"""
下载群文件里的access.log-20191119
通过正则表达式匹配，找出文件中所有访问记录里
访问次数最多的前10个IP，访问最频繁的前10个页面，并使用pyechart画出饼状图
"""


# Python 3.5.2

import re
from pyecharts import Pie # 这个错误了吧？from pyecharts.charts import Pie



# log
# `ip` - - [date +timezone] "method path protocol" status-code length "link" `proxy`
# `ip` - - [date +timezone] "method" status-code length "link" `proxy`

class Log:
    ip = r'(?P<ip>[\d\.]{4,})'
    datetime = r'(?P<datetime>.*)'
    method = r'(?P<method>GET|HEAD|POST)'
    path = r'(?P<path>.*)'
    # re.match(r'(?P<ip>[\d\.]{4,}) - - (?P<_>.*)"(?P<method>GET|HEAD|POST) (?P<path>.*) HTTP', a).groupdict()
    regex_pattern = '{} - - {}"{} {} HTTP'.format(ip, datetime, method, path)
    regex_compile = re.compile(regex_pattern)

    def __init__(self, source, encode='utf-8'):
        self.ips = {}
        self.paths = {}
        if isinstance(source, str):
            try:
                with open(file=source, mode='r', encoding=encode) as log:
                    self.lines = log.readlines()
            except Exception as e:
                raise e
        elif isinstance(source, (list, tuple)):
            self.lines = source
        else:
            raise Exception(
                'soure shoulb be `str(filepath)`, `list` or `tuple`')

    def parse(self) -> None:
        for line in self.lines:
            match_res = self.regex_compile.match(line)
            if match_res:
                ip = match_res.groupdict().get('ip')
                path = match_res.groupdict().get('path')
                self.ips[ip] = self.ips.get(ip, 0) + 1
                self.paths[path] = self.paths.get(path, 0) + 1

    def topTenData(self, name: str) -> tuple:
        def index_item(index: int, lst: list):
            if lst:
                return [lst[0][index]] + index_item(index, lst[1:])
            return []

        try:
            self.x = getattr(self, name)
        except AttributeError as e:
            raise e
        ten_items = sorted(
            self.x.items(), key=lambda x: x[1], reverse=True)[:10]
        ten_keys = index_item(0, ten_items)
        ten_values = index_item(1, ten_items)
        return ten_keys, ten_values

    def drawTopTen(self, name: str, fname: str = 'topten') -> None:
        keys, values = self.topTenData(name)
        pie = Pie('{} pie chat'.format(name), title_pos='center')
        pie.add(
            "",
            keys,
            values,
            radius=[40, 75],
            label_text_color=None,
            is_label_show=True,
            legend_orient="vertical",
            legend_pos="left",
        ).render('{}.html'.format(fname))


if __name__ == '__main__':
    fname = 'access.log-20191119'
    L = Log(fname)
    L.parse()
    L.drawTopTen('ips', 'ips')
    L.drawTopTen('paths', 'paths')
